package main

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strconv"
	"time"

	"gofw-im/lib/define"
	"gofw-im/lib/logger"
	"gofw-im/lib/net"
	"gofw-im/lib/proto"
)

type retData struct {
	Code int
	Msg  string
}

func InitHTTP() (err error) {
	httpServeMux := http.NewServeMux()
	httpServeMux.HandleFunc("/api/v1/push", Push)
	httpServeMux.HandleFunc("/api/v1/pushRoom", PushRoom)
	httpServeMux.HandleFunc("/api/v1/count", Count)
	logger.Info.Printf("start http listen:%s", conf.Base.HttpAddr)
	var addr string
	if _, addr, err = net.ParseNetwork(conf.Base.HttpAddr); err != nil {
		logger.Error.Printf("InitHTTP ParseNetwork error : %s", err)
		return
	}
	go httpListen(httpServeMux, addr)
	select {}
}

func httpListen(mux *http.ServeMux, addr string) {
	httpServer := &http.Server{
		Handler:      mux,
		ReadTimeout:  conf.Base.HTTPReadTimeout,
		WriteTimeout: conf.Base.HTTPWriteTimeout,
		Addr:         addr,
	}
	//logger.Info.Printf("logic initHTTP httpListen httpServer.addr: %s", httpServer.Addr)
	httpServer.SetKeepAlivesEnabled(true)
	if err := httpServer.ListenAndServe(); err != nil {
		logger.Error.Printf("server.ListenAndServe() error(%v)", err)
		panic(err)
	}
}

func Push(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Method Not Allowed", 405)
		return
	}

	var (
		auth         = r.URL.Query().Get("auth")
		acceptUserId = r.URL.Query().Get("userId")
		err          error
		bodyBytes    []byte
		body         string
		formUserInfo *proto.Router
		res          = map[string]interface{}{"code": define.SUCCESS_REPLY, "msg": define.SUCCESS_REPLY_MSG}
		sendData     *proto.Send
	)

	defer retPWrite(w, r, res, &body, time.Now())

	if formUserInfo, err = getRouter(auth); err != nil {
		logger.Error.Printf("get router error : %s", err)
		return
	}
	logger.Info.Printf("push round userId %s", formUserInfo.UserId)

	if bodyBytes, err = ioutil.ReadAll(r.Body); err != nil {
		res["code"] = define.NETWORK_ERR
		res["msg"] = define.NETWORK_ERR_MSG
		logger.Error.Printf("get router error : %s", err)
		return
	}

	sid, err := strconv.ParseInt(RedisCli.Get(getKey(acceptUserId)).Val(), 10, 8)
	if err != nil {
		res["code"] = define.SEND_ERR
		res["msg"] = define.SEND_ERR_MSG
		logger.Error.Printf("router err %v", err)
		return
	}

	json.Unmarshal(bodyBytes, &sendData)
	sendData.FormUserName = formUserInfo.UserName
	sendData.FormUserId = formUserInfo.UserId
	sendData.Op = define.OP_SINGLE_SEND
	if bodyBytes, err = json.Marshal(sendData); err != nil {
		logger.Error.Printf("redis Publish err: %s", err)
		return
	}
	body = string(bodyBytes)

	if err = RedisPublishCh(int8(sid), acceptUserId, bodyBytes); err != nil {
		logger.Error.Printf("redis Publish err: %s", err)

	}
}

func PushRoom(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Method Not Allowed", 405)
	}
	var (
		auth         = r.URL.Query().Get("auth")
		err          error
		bodyBytes    []byte
		body         string
		sendData     *proto.Send
		formUserInfo *proto.Router
		res          = map[string]interface{}{"code": define.SUCCESS_REPLY, "msg": define.SUCCESS_REPLY_MSG}
	)

	// get roomId
	rid, err := strconv.ParseInt(r.URL.Query().Get("rid"), 10, 32)
	if err != nil {
		logger.Error.Printf("rid invalid : %s", rid)
		return
	}
	if formUserInfo, err = getRouter(auth); err != nil {
		logger.Error.Printf("get router error : %s", err)
		return
	}
	if formUserInfo.UserId == "" {
		logger.Error.Printf("userId invalid : ")
		return
	}

	if bodyBytes, err = ioutil.ReadAll(r.Body); err != nil {
		res["code"] = define.NETWORK_ERR
		res["msg"] = define.NETWORK_ERR_MSG
		logger.Error.Printf("get router error : %s", err)
		return
	}
	defer retPWrite(w, r, res, &body, time.Now())
	body = string(bodyBytes)
	logger.Info.Printf("get bodyBytes : %s", body)

	json.Unmarshal(bodyBytes, &sendData)
	sendData.FormUserName = formUserInfo.UserName
	sendData.FormUserId = formUserInfo.UserId
	sendData.Op = define.OP_ROOM_SEND
	if bodyBytes, err = json.Marshal(sendData); err != nil {
		logger.Error.Printf("redis Publish room err: %s", err)
		return
	}
	if err = RedisPublishRoom(int32(rid), bodyBytes); err != nil {
		logger.Error.Printf("redis Publish room err: %s", err)
	}
	res["code"] = define.SUCCESS_REPLY
	res["msg"] = define.SUCCESS_REPLY_MSG
	return
}

func Count(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Method Not Allowed", 405)
	}
	var (
		ridStr = r.URL.Query().Get("rid")
		count  int
		err    error
		rid    int
		res    = map[string]interface{}{"code": define.SEND_ERR, "msg": define.SEND_ERR_MSG}
	)

	if count, err = RedisCli.Get(getKey(ridStr)).Int(); err != nil {
		logger.Error.Printf("Count redis get rid:%d, count err: %s", err)
		return
	}

	if rid, err = strconv.Atoi(ridStr); err != nil {
		logger.Error.Printf("Count redis Count rid:%d, count err: %s", rid, err)
		return
	}

	if err = RedisPublishRoomCount(int32(rid), count); err != nil {
		logger.Error.Printf("Count redis RedisPublishRoomCount err: %s", err)
		return
	}

	res["code"] = define.SUCCESS_REPLY
	res["msg"] = define.SUCCESS_REPLY_MSG
	defer retWrite(w, r, res, time.Now())
	return
}

func retPWrite(w http.ResponseWriter, r *http.Request, res map[string]interface{}, body *string, start time.Time) {
	data, err := json.Marshal(res)
	if err != nil {
		logger.Error.Printf("json.Marshal(\"%v\") error(%v)", res, err)
		return
	}
	dataStr := string(data)
	w.Header().Set("Access-Control-Allow-Origin", "*")             //允许访问所有域
	w.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的类型
	w.Header().Set("content-type", "application/json")
	if _, err := w.Write([]byte(dataStr)); err != nil {
		logger.Error.Printf("w.Write(\"%s\") error(%v)", dataStr, err)
	}

	logger.Info.Printf("req: \"%s\", post: \"%s\", res:\"%s\", ip:\"%s\", time:\"%fs\"", r.URL.String(), *body, dataStr, r.RemoteAddr, time.Now().Sub(start).Seconds())
}

func retWrite(w http.ResponseWriter, r *http.Request, res map[string]interface{}, start time.Time) {
	data, err := json.Marshal(res)
	if err != nil {
		logger.Error.Printf("json.Marshal(\"%v\") error(%v)", res, err)
		return
	}
	dataStr := string(data)
	w.Header().Set("Access-Control-Allow-Origin", "*")             // 允许访问所有域
	w.Header().Add("Access-Control-Allow-Headers", "Content-Type") // header的类型
	w.Header().Set("content-type", "application/json")
	if _, err := w.Write([]byte(dataStr)); err != nil {
		logger.Error.Printf("w.Write(\"%s\") error(%v)", dataStr, err)
	}

	logger.Info.Printf("req: \"%s\", get: res:\"%s\", ip:\"%s\", time:\"%fs\"", r.URL.String(), dataStr, r.RemoteAddr, time.Now().Sub(start).Seconds())
}
